package com.cysyz.web.modules.base.permission.interceptor;


import com.cysyz.mylib.myfilter.MyFilter;
import com.cysyz.mylib.myfilter.impl.PatternFilter;
import com.cysyz.mylib.utils.PropertiesUtil;
import com.cysyz.web.modules.base.permission.annotation.Module;
import com.cysyz.web.modules.base.permission.annotation.ModuleFunction;
import com.cysyz.web.modules.base.permission.service.PermissionService;
import com.cysyz.web.modules.base.permission.support.ModuleFunctionType;
import com.cysyz.web.modules.base.permission.support.PermissionContentType;
import com.cysyz.web.modules.base.support.SysConstants;
import com.cysyz.web.modules.base.user.domain.SysUser;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;

public class PermissionInterceptorSpringMVC implements HandlerInterceptor {
    private static final long serialVersionUID = -3169797944561956487L;
    private MyFilter permissionCheckFilter;
    private List<String> includes = new ArrayList<String>();

    private Boolean isCheckPermission;

    Properties permissionProperties;

    @Resource
    private PermissionService permissonService;

	public PermissionInterceptorSpringMVC() {

        permissionProperties = PropertiesUtil.getProperties(PermissionInterceptorSpringMVC.class.getResource("/permission.properties").getFile());


        String excludesCsv = permissionProperties.getProperty("permission.check.excludes");

        isCheckPermission = new Boolean(permissionProperties.getProperty("permission.switch"));

        final Map<String, Pattern> patternsMap =  new HashMap<>();

        List<String> excludes = Arrays.asList(excludesCsv.split(","));

        for (String exclude : excludes) {
            patternsMap.put(exclude, Pattern.compile(exclude.trim()));
        }

        //FrameController.class.getMethod("com.cysyz.springmvc.test.frame");
        String notNeedLoginCheckCsv = permissionProperties.getProperty("login.check.excludes");

        loginFilter = new PatternFilter("", notNeedLoginCheckCsv);
        permissionCheckFilter = new PatternFilter(includes, excludes);
	}

    private MyFilter loginFilter;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {


        if (!isCheckPermission) {
            return true;
        }

        SysUser sysUser = (SysUser) httpServletRequest.getSession().getAttribute(SysConstants.CURRENT_LOGIN_SYSUSER);

        //如果没有登录，查看请求是否在过滤列表中。如果在，通过；否则返回错误
        if (sysUser == null) {

            if (!loginFilter.filter(httpServletRequest.getServletPath())) {
                return true;
            }
            httpServletResponse.setHeader("Content-type", PermissionContentType.LOGIN_CHECK_FAIL.toString());
            return false;
        }

        boolean allCheckPass = false;

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        Class<?> declaringClass = method.getDeclaringClass();
        if (declaringClass.isAnnotationPresent(Module.class)) {
            String module = declaringClass.getAnnotation(Module.class).code();
            String methodName = method.getName();
            String moduleFunction = methodName;

            ModuleFunction annotation = null;
            if (method.isAnnotationPresent(ModuleFunction.class)) {
              annotation = method.getAnnotation(ModuleFunction.class);
            }

            if (methodName.endsWith("UI") && (annotation == null || annotation.moduleFunctionType() != ModuleFunctionType.MENU)) {
                moduleFunction = methodName.substring(0, methodName.indexOf("UI"));
            }

            //如果用户没有权限进行操作，那么返回首页
            if (sysUser != null && permissonService.hasPermission(sysUser, module, moduleFunction)) {
                allCheckPass = true;
            } else {
                allCheckPass = false;
            }
        }

        if (!allCheckPass) {
            allCheckPass = !permissionCheckFilter.filter(method.getName());
        }

        if (!allCheckPass) {
            httpServletRequest.getSession().removeAttribute(SysConstants.CURRENT_LOGIN_SYSUSER);
            httpServletResponse.setHeader("Content-type", PermissionContentType.PERMISSION_CHECK_FAIL.toString());

        }
        return allCheckPass;
    }



    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}
